import { Request, Response } from 'express';
import User, { IUser } from '@/models/User';
import { generateToken, generateRefreshToken, verifyToken, TokenPayload } from '@/utils/jwt';
import { hashPassword, comparePassword } from '@/utils/password';
import { createSuccessResponse, createErrorResponse } from '@/utils/response';
import { ErrorCode } from '@/types';

// 用户注册
export const register = async (req: Request, res: Response): Promise<Response | void> => {
  try {
    const { username, email, password, confirmPassword } = req.body;

    // 验证必填字段
    if (!username || !email || !password || !confirmPassword) {
      return res.status(400).json(
        createErrorResponse('所有字段都是必填的')
      );
    }

    // 验证密码一致性
    if (password !== confirmPassword) {
      return res.status(400).json(
        createErrorResponse('密码和确认密码不一致')
      );
    }

    // 验证密码强度
    if (password.length < 6) {
      return res.status(400).json(
        createErrorResponse('密码至少需要6个字符')
      );
    }

    // 检查用户是否已存在
    const existingUser = await User.findOne({
      $or: [{ email }, { username }]
    });

    if (existingUser) {
      const field = existingUser.email === email ? '邮箱' : '用户名';
      return res.status(400).json(
        createErrorResponse(`该${field}已被注册`)
      );
    }

    // 加密密码
    const hashedPassword = await hashPassword(password);

    // 创建用户
    const user = new User({
      username,
      email,
      password: hashedPassword
    });

    await user.save();

    // 生成Token
    const tokenPayload: TokenPayload = {
      id: (user._id as any).toString(),
      email: user.email,
      username: user.username
    };
    
    const token = generateToken(tokenPayload);
    const refreshToken = generateRefreshToken(tokenPayload);

    res.status(201).json(
      createSuccessResponse('注册成功', {
        token,
        refreshToken,
        user: {
          id: user._id,
          username: user.username,
          email: user.email,
          avatar: user.avatar,
          role: user.role,
          isActive: user.isActive
        }
      })
    );
  } catch (error: any) {
    console.error('注册错误:', error);
    
    // 处理MongoDB验证错误
    if (error.name === 'ValidationError') {
      const messages = Object.values(error.errors).map((err: any) => err.message);
      return res.status(400).json(
        createErrorResponse('数据验证失败', messages.join(', '))
      );
    }

    // 处理重复键错误
    if (error.code === 11000) {
      const field = Object.keys(error.keyPattern)[0];
      const fieldName = field === 'email' ? '邮箱' : '用户名';
      return res.status(400).json(
        createErrorResponse(`该${fieldName}已被注册`)
      );
    }

    res.status(500).json(
      createErrorResponse('服务器内部错误')
    );
  }
};

// 用户登录
export const login = async (req: Request, res: Response): Promise<Response | void> => {
  try {
    const { email, password } = req.body;

    // 验证必填字段
    if (!email || !password) {
      return res.status(400).json(
        createErrorResponse('邮箱和密码都是必填的')
      );
    }

    // 查找用户（包含密码字段）
    const user = await User.findOne({ email }).select('+password');
    
    if (!user) {
      return res.status(401).json(
        createErrorResponse('邮箱或密码错误')
      );
    }

    // 检查用户是否激活
    if (!user.isActive) {
      return res.status(401).json(
        createErrorResponse('账户已被禁用，请联系管理员')
      );
    }

    // 验证密码
    const isPasswordValid = await comparePassword(password, user.password);
    
    if (!isPasswordValid) {
      return res.status(401).json(
        createErrorResponse('邮箱或密码错误')
      );
    }

    // 更新最后登录时间
    user.lastLoginAt = new Date();
    await user.save();

    // 生成Token
    const tokenPayload: TokenPayload = {
      id: (user._id as any).toString(),
      email: user.email,
      username: user.username
    };
    
    const token = generateToken(tokenPayload);
    const refreshToken = generateRefreshToken(tokenPayload);

    res.json(
      createSuccessResponse('登录成功', {
        token,
        refreshToken,
        user: {
          id: user._id,
          username: user.username,
          email: user.email,
          avatar: user.avatar,
          role: user.role,
          isActive: user.isActive,
          lastLoginAt: user.lastLoginAt
        }
      })
    );
  } catch (error) {
    console.error('登录错误:', error);
    res.status(500).json(
      createErrorResponse('服务器内部错误')
    );
  }
};

// 刷新Token
export const refreshToken = async (req: Request, res: Response): Promise<Response | void> => {
  try {
    const { refreshToken: token } = req.body;

    if (!token) {
      return res.status(401).json(
        createErrorResponse('刷新令牌是必填的')
      );
    }

    // 验证刷新令牌
    const decoded = verifyToken(token);
    
    // 查找用户
    const user = await User.findById(decoded.id);
    
    if (!user || !user.isActive) {
      return res.status(401).json(
        createErrorResponse('用户不存在或已被禁用')
      );
    }

    // 生成新的Token
    const tokenPayload: TokenPayload = {
      id: (user._id as any).toString(),
      email: user.email,
      username: user.username
    };
    
    const newToken = generateToken(tokenPayload);
    const newRefreshToken = generateRefreshToken(tokenPayload);

    res.json(
      createSuccessResponse('令牌刷新成功', {
        token: newToken,
        refreshToken: newRefreshToken
      })
    );
  } catch (error) {
    console.error('刷新令牌错误:', error);
    res.status(401).json(
      createErrorResponse('无效的刷新令牌')
    );
  }
};

// 获取当前用户信息
export const getCurrentUser = async (req: Request, res: Response): Promise<Response | void> => {
  try {
    const userId = (req as any).user?.id;
    
    if (!userId) {
      return res.status(401).json(
        createErrorResponse('未授权访问')
      );
    }

    const user = await User.findById(userId);
    
    if (!user) {
      return res.status(404).json(
        createErrorResponse('用户不存在')
      );
    }

    res.json(
      createSuccessResponse('获取用户信息成功', {
        user: {
          id: user._id,
          username: user.username,
          email: user.email,
          avatar: user.avatar,
          role: user.role,
          isActive: user.isActive,
          lastLoginAt: user.lastLoginAt,
          createdAt: user.createdAt
        }
      })
    );
  } catch (error) {
    console.error('获取用户信息错误:', error);
    res.status(500).json(
      createErrorResponse('服务器内部错误')
    );
  }
};

// 修改密码
export const changePassword = async (req: Request, res: Response): Promise<Response | void> => {
  try {
    const userId = (req as any).user?.id;
    const { currentPassword, newPassword, confirmPassword } = req.body;

    // 验证必填字段
    if (!currentPassword || !newPassword || !confirmPassword) {
      return res.status(400).json(
        createErrorResponse('所有字段都是必填的')
      );
    }

    // 验证新密码一致性
    if (newPassword !== confirmPassword) {
      return res.status(400).json(
        createErrorResponse('新密码和确认密码不一致')
      );
    }

    // 验证新密码强度
    if (newPassword.length < 6) {
      return res.status(400).json(
        createErrorResponse('新密码至少需要6个字符')
      );
    }

    // 查找用户（包含密码字段）
    const user = await User.findById(userId).select('+password');
    
    if (!user) {
      return res.status(404).json(
        createErrorResponse('用户不存在')
      );
    }

    // 验证当前密码
    const isCurrentPasswordValid = await comparePassword(currentPassword, user.password);
    
    if (!isCurrentPasswordValid) {
      return res.status(400).json(
        createErrorResponse('当前密码错误')
      );
    }

    // 加密新密码
    const hashedNewPassword = await hashPassword(newPassword);
    
    // 更新密码
    user.password = hashedNewPassword;
    await user.save();

    res.json(
      createSuccessResponse('密码修改成功')
    );
  } catch (error) {
    console.error('修改密码错误:', error);
    res.status(500).json(
      createErrorResponse('服务器内部错误')
    );
  }
};

// 注销登录
export const logout = async (req: Request, res: Response): Promise<Response | void> => {
  try {
    // 在实际应用中，这里可以将token加入黑名单
    // 目前只是返回成功响应
    res.json(
      createSuccessResponse('注销成功')
    );
  } catch (error) {
    console.error('注销错误:', error);
    res.status(500).json(
      createErrorResponse('服务器内部错误')
    );
  }
};